From ebdf5f581d4e93c577f4cdb2e47e30e393e61157 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Florian=20M=C3=BCllner?= Date: Fri, 23 Oct 2015 18:07:41 +0200 Subject: [PATCH] widget: Add :focus-on-click property There are currently three widget that implement such a property, and there are other widgets for which the behavior can make sense. It seems like a good time to add the property to GtkWidget itself so subclasses can choose to respect it without adding their own property. https://bugzilla.gnome.org/show_bug.cgi?id=757269 --- gtk/gtkwidget.c | 82 +++++++++++++++++++++++++++++++++++++++++- gtk/gtkwidget.h | 5 +++ gtk/gtkwidgetprivate.h | 1 + 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index fd53f5876c..42bf421cee 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -575,6 +575,7 @@ enum { PROP_CAN_FOCUS, PROP_HAS_FOCUS, PROP_IS_FOCUS, + PROP_FOCUS_ON_CLICK, PROP_CAN_DEFAULT, PROP_HAS_DEFAULT, PROP_RECEIVES_DEFAULT, @@ -1196,6 +1197,25 @@ gtk_widget_class_init (GtkWidgetClass *klass) FALSE, GTK_PARAM_READWRITE); + /** + * GtkWidget:focus-on-click: + * + * Whether the widget should grab focus when it is clicked with the mouse. + * + * This property is only relevant for widgets that can take focus. + * + * Before 3.20, several widgets (GtkButton, GtkFileChooserButton, + * GtkComboBox) implemented this property individually. + * + * Since: 3.20 + */ + widget_props[PROP_FOCUS_ON_CLICK] = + g_param_spec_boolean ("focus-on-click", + P_("Focus on click"), + P_("Whether the widget should grab focus when it is clicked with the mouse"), + TRUE, + GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); + widget_props[PROP_CAN_DEFAULT] = g_param_spec_boolean ("can-default", P_("Can default"), @@ -3695,6 +3715,9 @@ gtk_widget_set_property (GObject *object, if (g_value_get_boolean (value)) gtk_widget_grab_focus (widget); break; + case PROP_FOCUS_ON_CLICK: + gtk_widget_set_focus_on_click (widget, g_value_get_boolean (value)); + break; case PROP_CAN_DEFAULT: gtk_widget_set_can_default (widget, g_value_get_boolean (value)); break; @@ -3885,6 +3908,9 @@ gtk_widget_get_property (GObject *object, case PROP_IS_FOCUS: g_value_set_boolean (value, gtk_widget_is_focus (widget)); break; + case PROP_FOCUS_ON_CLICK: + g_value_set_boolean (value, gtk_widget_get_focus_on_click (widget)); + break; case PROP_CAN_DEFAULT: g_value_set_boolean (value, gtk_widget_get_can_default (widget)); break; @@ -4329,7 +4355,8 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class) priv->redraw_on_alloc = TRUE; priv->alloc_needed = TRUE; priv->alloc_needed_on_child = TRUE; - + priv->focus_on_click = TRUE; + switch (_gtk_widget_get_direction (widget)) { case GTK_TEXT_DIR_LTR: @@ -8448,6 +8475,59 @@ gtk_widget_is_focus (GtkWidget *widget) return FALSE; } +/** + * gtk_widget_set_focus_on_click: + * @widget: a #GtkWidget + * @focus_on_click: whether the widget should grab focus when clicked with the mouse + * + * Sets whether the widget should grab focus when it is clicked with the mouse. + * Making mouse clicks not grab focus is useful in places like toolbars where + * you don’t want the keyboard focus removed from the main area of the + * application. + * + * Since: 3.20 + **/ +void +gtk_widget_set_focus_on_click (GtkWidget *widget, + gboolean focus_on_click) +{ + GtkWidgetPrivate *priv; + + g_return_if_fail (GTK_IS_WIDGET (widget)); + + priv = widget->priv; + + focus_on_click = focus_on_click != FALSE; + + if (priv->focus_on_click != focus_on_click) + { + priv->focus_on_click = focus_on_click; + + g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_FOCUS_ON_CLICK]); + } +} + +/** + * gtk_widget_get_focus_on_click: + * @widget: a #GtkWidget + * + * Returns whether the widget should grab focus when it is clicked with the mouse. + * See gtk_widget_set_focus_on_click(). + * + * Returns: %TRUE if the widget should grab focus when it is clicked with + * the mouse. + * + * Since: 3.20 + **/ +gboolean +gtk_widget_get_focus_on_click (GtkWidget *widget) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + + return widget->priv->focus_on_click; +} + + /** * gtk_widget_set_can_default: * @widget: a #GtkWidget diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index 61881c2ed6..d428917062 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -783,6 +783,11 @@ GDK_AVAILABLE_IN_3_2 gboolean gtk_widget_has_visible_focus (GtkWidget *widget); GDK_AVAILABLE_IN_ALL void gtk_widget_grab_focus (GtkWidget *widget); +GDK_AVAILABLE_IN_3_20 +void gtk_widget_set_focus_on_click (GtkWidget *widget, + gboolean focus_on_click); +GDK_AVAILABLE_IN_3_20 +gboolean gtk_widget_get_focus_on_click (GtkWidget *widget); GDK_AVAILABLE_IN_ALL void gtk_widget_set_can_default (GtkWidget *widget, diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index 484c1f38e1..b1755969f9 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -56,6 +56,7 @@ struct _GtkWidgetPrivate guint sensitive : 1; guint can_focus : 1; guint has_focus : 1; + guint focus_on_click : 1; guint can_default : 1; guint has_default : 1; guint receives_default : 1; -- 2.30.2